#pragma once
#include <stdint.h>
#include "Character/Part.h"
#include "Scene/Path.h"
#include "Common/SceneDefine.h"
#include "Common/CharacterDefine.h"
#include "ProtoBuffer/AllProtocol.h"
//#include "AllProtocol.h"
#include "Common/DuplicateDefine.h"
#include "Common/TableData/DuplicateDuplicateCfg.h"
#include "Common/TableData/DuplicateGroupCfg.h"

class DuplicatePart : public Part
{
	typedef void (DuplicatePart::*pFunc)(const char*, uint32_t);
	typedef std::map<uint32_t, pFunc> mapMsgFunc;
	mapMsgFunc   m_mapMsgfunc;
public:
	///////////////////////////////  Part  ///////////////////////////////////////////
	virtual bool Init(Creature *pMaster, uint32_t partType, CharacterDBInfo* pCharacterDB = nullptr);
	virtual bool UnInit();
	virtual bool OnMsgHandle(uint32_t cmd, const char* data, uint32_t len);
	virtual void OnExecute(uint16_t nEventID, uint64_t nSrcID, uint8_t bySrcType, void *pContext, int32_t nLen);
	virtual void OnTimer(uint32_t nTimerID);
	virtual bool SynClient(PlayerClientInfo& playerInfo);
	virtual bool SaveDB(CharacterDBInfo& characterDB);
	//////////////////////////////// IDuplicatePart  //////////////////////////////////////////
	//副本完成
	virtual void DuplicateFinish(DuplicateResult &result);
	//通知离开副本
	virtual void NotifyLeave(uint32_t nDuplicateID,int8_t byKeyType);
	//准备进入副本
	virtual int32_t PrepareEnter(uint32_t duplicateId, uint32_t sceneId, int8_t keyType, uint64_t keyValue);
	//通知进入副本
	virtual bool NotifyEnter(uint32_t duplicateId, uint32_t sceneId, uint32_t bornId = 0);
	//通知进入副本失败
	void NotifyEnterFailed(uint32_t nDuplicateID, int32_t retcode);
	//通知进入成功
	virtual void NotifyEnterSuccess(DupEnterParam &enterParam);
	//是否能进副本(副本房间专用)
	virtual int32_t CanEnterDup(uint32_t dupId);
	//重连
	virtual void NotifyReconnect(DupEnterParam &enterParam);
	//////////////////////////////////////////////////////////////////////////
	virtual bool DailyUpdate(uint64_t unixSec);
	virtual bool WeekUpdate(uint64_t unixSec);
public:
	//获取副本组
	SDuplicateGroup *GetGroup(uint32_t groupId);
	//获取副本
	SDuplicate *GetDuplicate(uint32_t duplicateId);
	//是否能进入副本
	int32_t CanEnter(const DuplicateDuplicateCfgInfo *pCfg,const DuplicateGroupCfgInfo *pGroupCfg);
	//是否能进入副本
	int32_t CanEnter(int8_t keyType,uint64_t keyValue,const DuplicateDuplicateCfgInfo *pCfg, const DuplicateGroupCfgInfo *pGroupCfg);
	//能否进入新手副本
	int32_t CanEnterNew(uint32_t areaId,Point3<float>pos, const DuplicateDuplicateCfgInfo *pCfg, const DuplicateGroupCfgInfo *pGroupCfg);
	//能否进入剧情副本
	int32_t CanEnterStory(uint32_t areaId, Point3<float>pos, const DuplicateDuplicateCfgInfo *pCfg, const DuplicateGroupCfgInfo *pGroupCfg);
	//是否能进入塔防副本
	int32_t CanEnterTower(const DuplicateDuplicateCfgInfo *pCfg, const DuplicateGroupCfgInfo *pGroupCfg);
	//是否能进入守护副本
	int32_t CanEnterGuard(const DuplicateDuplicateCfgInfo *pCfg, const DuplicateGroupCfgInfo *pGroupCfg);
	//是否能进入单人活动副本
	int32_t CanEnterSingleA(const DuplicateDuplicateCfgInfo *pCfg, const DuplicateGroupCfgInfo *pGroupCfg);
	//能否进入天梯副本
	int32_t CanEnterLadder(const DuplicateDuplicateCfgInfo *pCfg, const DuplicateGroupCfgInfo *pGroupCfg);

	//副本奖励
	void DupReward(const DuplicateDuplicateCfgInfo *pCfg, Duplicate_ResultRsp &rsp);
	//更新副本开启
	void UpdateDupOpen(SET_UINT32 &setAdd);
	//设置下一个挑战层副本信息
	void SetNextLayerInfo(DupLadderProto *proto);
	//更新天梯
	void UpdateLadder();
private:
	//登录检查副本组进入和奖励次数以及购买次数刷新
	void CheckDupGroup();
	//进入副本返回的数据
	bool OnDupEnterRsp(DupEnterParam &enterParam, Duplicate_EnterRsp &rsp);
	//是否有进入副本需要的物品
	bool HasDupItem(const DuplicateGroupCfgInfo *pGroupCfg);
	//扣除进入副本需要的物品
	bool RemoveDupItem(const DuplicateGroupCfgInfo *pGroupCfg);
private:
	//副本信息
	void Info(const char *data, uint32_t len);
	//进入副本
	void Enter(const char *data, uint32_t len);
	//离开副本
	void Leave(const char *data, uint32_t len);
	//复活
	void Relive(const char *data, uint32_t len);
	//进入区域
	void EnterArea(const char *data, uint32_t len);
	//更新副本
	void UpdateDuplicate(Duplicate_UpdateRsp &update);
	//邀请进入副本
	void InviteEnter(const char *data, uint32_t len);
	//回复邀请
	void ReplyInvite(const char *data, uint32_t len);
	//开始挑战（竞技场）
	void StartChallenge(const char *data, uint32_t len);
	//加入排队
	void JoinQueue(const char *data, uint32_t len);
	//掉落数据
	void DropData(const char *data, uint32_t len);
public:
	DuplicatePart();
	virtual ~DuplicatePart();
private:
	//副本
	DuplicateMap m_mapDuplicate;
	//副本组
	DuplicateGroupMap m_mapGroup;
	//所有的副本ID
	SET_UINT32 m_setAllDuplicate;
	//
	SET_UINT32 m_setOpenDup;

	//历史层数
	int32_t m_historyLayer;
	//当前层数
	int32_t m_curLayer;
	//上次通关天梯时间
	uint64_t m_lastLayerTime;
};
